package com.wichatbackapi.service.Impl;

import com.wichatbackapi.domain.AuthenticationContextHolder;
import com.wichatbackapi.domain.LoginUser;
import com.wichatbackapi.domain.doa.SysUser;
import com.wichatbackapi.redis.RedisCache;
import com.wichatbackapi.result.ResponseResult;
import com.wichatbackapi.service.LoginServcie;
import com.wichatbackapi.service.SysPasswordService;
import com.wichatbackapi.service.SysUserService;
import com.wichatbackapi.utils.JwtUtil;
import com.wichatbackapi.utils.SecurityUtils;
import com.wichatbackapi.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

@Service
@Slf4j
public class LoginServiceImpl implements LoginServcie {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private SysUserService userService;
    @Autowired
    private SysPasswordService passwordService;

    @Override
    public ResponseResult login(SysUser sysUser) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(sysUser.getUserName(), sysUser.getPassword());
        Authentication authenticate = null;
        // 捕获AuthenticationException异常
        try {
            // 设置自定义Authentication上下文对象方便自定义校验
            AuthenticationContextHolder.setContext(authenticationToken);
            //进行认证返回对象判断是否通过认证，authenticate会调用UserDetails中的loadUserByUsername方法
            authenticate = authenticationManager.authenticate(authenticationToken);
        } catch (AuthenticationException e) {
            log.error("运行时异常: ", e);//即秘密与数据库密码比对出错的情况
            String userName = sysUser.getUserName();
            switch (e.getMessage()){
                case "user_not_exist":
                    return new ResponseResult(402,"登录用户:"+userName+"不存在.");
                case "user_by_delete":
                    return new ResponseResult(402,"登录用户:"+userName+"已被删除.");
                case "user_by_stop":
                    return new ResponseResult(402,"登录用户:"+userName+"已被停用.");
                default:
                    // 返回错误信息
                    return new ResponseResult(500, e.getMessage());//前端页面返回的信息
            }
        }finally {
            // 清空上下文对象
            AuthenticationContextHolder.clearContext();
        }
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("登录失败，认证失败");
        }
        //判断是否验证码
        if(sysUser.getIsCode()!=null&&sysUser.getIsCode()){//需要进行验证码验证操作
            try {
                //判断前端传来的验证码与redis中的验证码是否相同
                if(!(redisCache.getCacheObject("checkCode:"+sysUser.getCodeKey()).equals(sysUser.getCode()))){
                    return new ResponseResult(402,"验证码错误或过期,请重试");
                }
            }catch (Exception e){
                return new ResponseResult(402,"验证码错误或过期,请重试");
            }
        }
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getUserId().toString();
        String jwt = JwtUtil.createJWT(userId);
        //authenticate存入redis
        redisCache.setCacheObject("login:"+userId,loginUser);
        //把token响应给前端
        HashMap<String,String> map = new HashMap<>();
        map.put("token",jwt);
        return new ResponseResult(200,"登陆成功",map);
    }

    /**
     * 注册接口
     * @param sysUser
     * @return
     */
    @Override
    public ResponseResult register(SysUser sysUser) {
        String msg = "注册成功";
        Integer code=200;
        if (StringUtils.isEmpty(sysUser.getUserName())) {
            code=400;
            msg = "用户名不能为空";
            return new ResponseResult(code,msg);

        }
        else if (StringUtils.isEmpty(sysUser.getPassword())) {
            code=400;
            msg = "用户密码不能为空";
            return new ResponseResult(code,msg);

        } else if (!userService.checkUserNameUnique(sysUser)) {
            code=400;
            msg = "保存用户'" + sysUser.getUserName() + "'失败，注册账号已存在";
            return new ResponseResult(code,msg);

        }

        sysUser.setPassword(SecurityUtils.encryptPassword(sysUser.getPassword()));
        boolean regFlag = userService.registerUser(sysUser);
        if (!regFlag) {
            msg = "注册失败,请联系系统管理人员";
            return new ResponseResult(code,msg);

        }
        return new ResponseResult(code,msg);
    }

    @Override
    public ResponseResult logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Long userid = loginUser.getUser().getUserId();
        redisCache.deleteObject("login:"+userid);
        return new ResponseResult(200,"退出成功");
    }

}

